package cn.com.git.example.module.service.impl;

import cn.com.git.example.common.ResultConstant;
import cn.com.git.example.common.ResultMsg;
import cn.com.git.example.common.auth.*;
import cn.com.git.example.common.util.object.JSONUtils;
import cn.com.git.example.common.util.object.MapperFacadeUtils;
import cn.com.git.example.common.util.security.CodecUtils;
import cn.com.git.example.common.util.security.JwtUtils;
import cn.com.git.example.module.service.AuthenticationCacheService;
import cn.com.git.example.module.service.AuthenticationService;
import cn.com.git.example.module.service.SysUserService;
import cn.com.git.example.module.service.dto.SysUserDTO;
import cn.com.git.example.module.service.query.SysUserListQuery;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

/**
 * @author zhangzhenfu
 * @Description
 * @date 2021/3/6 0006 9:26
 */
@Slf4j
@Service
public class AuthenticationServiceImpl implements AuthenticationService {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private AuthenticationCacheService authenticationCacheService;

    @Value("${auth.jwt.token.key}")
    private String jwtKey;

    /*=================================*/
    /*============ 鉴权 =============*/
    /*=================================*/
    @Override
    public ResultMsg<AuthenticationDTO> loginByPassword(String account, String password) {
        if (StringUtils.isEmpty(account)) {
            return new ResultMsg<>(AuthResultConstant.EMPTY_USERNAME, "账号为空", null);
        }
        if (StringUtils.isEmpty(password)) {
            return new ResultMsg<>(AuthResultConstant.EMPTY_PASSWORD, "密码为空", null);
        }
        SysUserListQuery query = new SysUserListQuery();
        query.setAccount(account);
        List<SysUserDTO> sysUserDTOList = sysUserService.listSysUser(query);
        if(CollectionUtils.isEmpty(sysUserDTOList)){
            return new ResultMsg<>(AuthResultConstant.INVALID_ACCOUNT,"用户不存在",null);
        }
        SysUserDTO sysUser = sysUserDTOList.get(0);
        if(sysUser==null){
            return new ResultMsg<>(AuthResultConstant.INVALID_ACCOUNT,"用户不存在",null);
        }
        String pw = CodecUtils.MD5(password);
        if(!pw.equals(sysUser.getPassword())){
            return new ResultMsg<>(AuthResultConstant.INVALID_PASSWORD,"密码错误",null);
        }
        //TODO 查询权限数据
        //组装信息
        AuthenticationDTO authenticationDTO = new AuthenticationDTO();
        authenticationDTO.setSysUser(MapperFacadeUtils.map(sysUser, AuthenticationDTO.SysUser.class));
        return new ResultMsg<>(ResultConstant.SUCCESS, null, authenticationDTO);
    }

    /**
     * 验证码验证
     *
     * @param loginProcessDTO 登录会话
     * @param verifyCode 验证码
     * @param request 请求
     * @return
     */
    @Override
    public ResultMsg<AuthenticationDTO> loginByVerifyCode(LoginProcessDTO loginProcessDTO, String verifyCode, HttpServletRequest request) {
        String loginProcessSessionId = loginProcessDTO.getSessionId();
        //验证码禁用
        if (loginProcessDTO.waitSeconds() > 0) {
            AuthenticationDTO authenticationDTO = new AuthenticationDTO();
            authenticationDTO.setLoginProcessSessionId(loginProcessSessionId);
            authenticationDTO.setVerifyCodeEnable(true);
            authenticationDTO.setWaitSeconds(loginProcessDTO.waitSeconds());
            return new ResultMsg(AuthResultConstant.DISABLED_LOGIN, null, authenticationDTO);
        }
        if (StringUtils.isEmpty(loginProcessDTO.getVerifyCode())) {
            return new ResultMsg(AuthResultConstant.INVALID_VERIFY_CODE);
        }
        if (StringUtils.isEmpty(verifyCode)) {
            return new ResultMsg(AuthResultConstant.EMPTY_VERIFY_CODE);
        }
        //匹配验证
        String dbVerifyCode = loginProcessDTO.getVerifyCode();
        if (!verifyCode.equals(dbVerifyCode)) {
            loginProcessDTO.failTimesIncrease();
            loginProcessDTO.setLastLoginFailTime(new Date());
            loginProcessDTO.setVerifyCode(null);//验证码使用过后需要重置
            this.modifyLoginProcess(loginProcessSessionId, loginProcessDTO);

            AuthenticationDTO authenticationDTO = new AuthenticationDTO();
            authenticationDTO.setLoginProcessSessionId(loginProcessSessionId);
            authenticationDTO.setVerifyCodeEnable(loginProcessDTO.verifyCodeEnable());
            authenticationDTO.setWaitSeconds(loginProcessDTO.waitSeconds());
            return new ResultMsg(AuthResultConstant.ERROR_VERIFY_CODE, null, authenticationDTO);
        }
        return new ResultMsg(ResultConstant.SUCCESS);
    }

    /**
     * 创建令牌
     *
     * @param authenticationDTO 鉴权信息
     * @return
     */
    @Override
    public String createToken(AuthenticationTokenDTO authenticationDTO) {
        return JwtUtils.createToken(AuthConstant.CLIENT_SESSION_TIMEOUT, Maps.newHashMap(), "system", authenticationDTO.getSysUser().getAccount(), JSONUtils.toJson(authenticationDTO), jwtKey);
    }

    /**
     * 添加 登录过程
     *
     * @param loginProcessSessionId 登录会话id
     * @param loginProcess          登录会话
     * @return
     */
    @Override
    public void addLoginProcess(String loginProcessSessionId, LoginProcessDTO loginProcess) {
        authenticationCacheService.setLoginProcess(loginProcessSessionId,loginProcess);
    }

    /**
     * 查询 登录过程
     *
     * @param loginProcessSessionId 登录会话id
     * @return
     */
    @Override
    public LoginProcessDTO findLoginProcess(String loginProcessSessionId) {
        return authenticationCacheService.getLoginProcess(loginProcessSessionId);
    }

    /**
     * 更新 登录过程
     *
     * @param loginProcessSessionId 登录会话id
     * @param loginProcess
     */
    @Override
    public void modifyLoginProcess(String loginProcessSessionId, LoginProcessDTO loginProcess) {
        authenticationCacheService.modifyLoginProcess(loginProcessSessionId,loginProcess);
    }

    /**
     * 移除 登录过程
     *
     * @param loginProcessSessionId 登录会话id
     * @return
     */
    @Override
    public void removeLoginProcess(String loginProcessSessionId) {
        authenticationCacheService.removeLoginProcess(loginProcessSessionId);
    }

    /*============================================*/
    /*=================登录状态===================*/
    /*============================================*/
    /**
     * 获取 登录状态
     *
     * @param account
     * @return
     */
    @Override
    public LoginStatusDTO getLoginStatus(String account) {
        return authenticationCacheService.getLoginStatus(account);
    }

    /**
     * 设置 登录状态
     *
     * @param account
     * @param loginStatus
     */
    @Override
    public void setLoginStatus(String account, LoginStatusDTO loginStatus) {
        authenticationCacheService.setLoginStatus(account,loginStatus);
    }

    /**
     * 修改 登录状态
     *
     * @param account
     * @param loginStatus
     */
    @Override
    public void modifyLoginStatus(String account, LoginStatusDTO loginStatus) {
        authenticationCacheService.modifyLoginStatus(account,loginStatus);
    }

    /**
     * 移除 登录状态
     *
     * @param account
     */
    @Override
    public void removeLoginStatus(String account) {
        authenticationCacheService.removeLoginStatus(account);
    }
}
